/* eslint-disable @typescript-eslint/no-explicit-any */
/* eslint-disable @typescript-eslint/no-empty-object-type */
import type ts from "typescript";
import {
  type ServiceDescription,
  type ServiceToSyncObj,
} from "./service-describe.js";

export function createCustomService<TService extends ServiceDescription>(
  id: string,
  info: ts.server.PluginCreateInfo,
  customService: ServiceToSyncObj<
    TService,
    { fileName: string; position: number }
  >,
): void {
  const tsCommandId = `_handleRpc${id}`;
  info.session?.addProtocolHandler(tsCommandId, (request) => {
    const msg = request.arguments as IRequestMessageWithFileInfo;

    if (!customService[msg.method]) {
      throw new Error(`Method ${msg.method} not found in custom service`);
    }

    const pos = msg.position;
    const sf = info.languageService.getProgram()?.getSourceFile(msg.file);
    const p = sf?.getPositionOfLineAndCharacter(pos.line, pos.char);

    if (p === undefined) {
      throw new Error(
        `Position ${pos.line}:${pos.char} not found in file ${msg.file}`,
      );
    }

    return {
      response: {
        result: customService[msg.method]({
          ...msg.args,
          fileName: msg.file,
          position: p,
        }),
        error: undefined,
      },
    };
  });
}

export interface IRequestMessage {
  method: string;
  args: {};
}

interface IRequestMessageWithFileInfo extends IRequestMessage {
  file: string;
  position: { line: number; char: number };
}

export interface IResponseMessage {
  result: any;
  error: any;
}
